package filter

import (
	"bytes"
	"io"
	"strings"
	"sync"

	"github.com/microcosm-cc/bluemonday"
)

// 一个空的Policy过滤器
// 用户可以自定义允许或禁止的HTMl标签、内容或属性
func NewPolicy() *bluemonday.Policy {
	return bluemonday.NewPolicy()
}

// 默认 UGCPolicy  XSS/HTML过滤器
var (
	onceUGC   sync.Once
	globalUGC *bluemonday.Policy
)

// getUGC 单例
func getUGC() *bluemonday.Policy {
	onceUGC.Do(func() {
		globalUGC = bluemonday.UGCPolicy()
		globalUGC.AllowElements("video", "audio")
		globalUGC.AllowAttrs("source", "controls", "poster").OnElements("video", "audio")
		globalUGC.AllowAttrs("src", "type").OnElements("source")
		// wangEditor
		globalUGC.AllowAttrs("data-w-e-type").OnElements("p", "div", "table", "ul", "li")
		globalUGC.AllowAttrs("style").OnElements("p", "div", "table", "th", "td")
	})
	return globalUGC
}

// SafeHtml 过滤富文本危险的HTML标签、内容或属性
func SafeHtml(s string) string {
	s = strings.TrimSpace(s)
	if len(s) < 1 {
		return ""
	}
	return getUGC().Sanitize(s)
}

// SafeHtmlBytes 过滤富文本危险的HTML标签、内容或属性
func SafeHtmlBytes(s []byte) []byte {
	if len(s) > 0 {
		s = bytes.TrimSpace(s)
	}
	if len(s) == 0 {
		return []byte{}
	}
	vs := getUGC().SanitizeBytes(s)
	if len(vs) == 0 {
		return []byte{}
	}
	return vs
}

// SafeHtmlReader 读取io.Reader, 过滤富文本危险的HTML标签、内容或属性
func SafeHtmlReader(s io.Reader) []byte {
	if s == nil {
		return []byte{}
	}
	vs := getUGC().SanitizeReader(s)
	if vs == nil {
		return []byte{}
	}
	vss := bytes.TrimSpace(vs.Bytes())
	if len(vss) == 0 {
		return []byte{}
	}
	return vss
}

// SafeMD 过滤MD文档中富文本危险的HTML标签、内容或属性
func SafeMD(s string) string {
	s = strings.TrimSpace(s)
	if len(s) < 1 {
		return ""
	}
	s = getUGC().Sanitize(s)
	// 保留MD 语法前缀字符 >
	s = strings.ReplaceAll(s, "&gt;", ">")
	return s
}
